/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/08/22
*/
#include "Parser.h"
#include <string.h>

EDUI_NAMESPACE_BEGIN

Parser::Parser(const char* text) : m_text(0), m_pos(0)
{
    if (text){
        size_t size = strlen(text) + 1;
        m_text = new char[size];
        strcpy(m_text, text);
        m_text[size- 1] = 0;
    }
}

Parser::~Parser()
{
    if (m_text){
        delete m_text;
        m_text = 0;
    }
}

Parser::Attribute* Parser::First()
{
    m_pos = m_text;
    return this->Next();
}

Parser::Attribute* Parser::Next()
{
    const char* p = m_pos;
    if (!p || !p[0]) return 0;

    int ignore = 0;
    m_attr.Reset("", "");

    do {
        if ('(' == p[0]){ ++ignore; continue; }
        else if (')' == p[0]){ --ignore; continue; }
        if (ignore) continue;

        if (':' == p[0]){
            m_attr.Reset(m_pos, p - m_pos, 0, 0);
            m_pos = p + 1;
        } else if (';' == p[0]){
            m_attr.Reset(0, 0, m_pos, p - m_pos);
            m_pos = p + 1;
            return &m_attr;
        }
    } while ((++p)[0]);
    
    return 0;
}

//------------------------------------------------//

Parser::Attribute::Attribute() : m_name(0), m_value(0)
{}

const char* Parser::Attribute::Name()
{
    return m_name;
}

const char* Parser::Attribute::Value()
{
    return m_value;
}

void Parser::Attribute::Reset(const char* name, const char* value)
{
    if (name){
        size_t size = strlen(name) + 1;
        if (m_name && size > strlen(m_name)){
            if (m_name){
                delete m_name;
                m_name = 0;
            }
        }
        if (!m_name) m_name = new char[size];
        strcpy(m_name, name);
        m_name[size - 1] = 0;
    }
    if (value){
        size_t size = strlen(value) + 1;
        if (m_value && size > strlen(m_value)){
            if (m_value){
                delete m_value;
                m_value = 0;
            }
        }
        if (!m_value) m_value = new char[size];
        strcpy(m_value, value);
        m_value[size - 1] = 0;
    }
}

void Parser::Attribute::Reset(const char* name, size_t namelen, const char* value, size_t valuelen)
{
    if (name){
        size_t size = namelen + 1;
        if (m_name && size > strlen(m_name)){
            if (m_name){
                delete m_name;
                m_name = 0;
            }
        }
        if (!m_name) m_name = new char[size];
        strncpy(m_name, name, namelen);
        m_name[size - 1] = 0;
    }
    if (value){
        size_t size = valuelen + 1;
        if (m_value && size > strlen(m_value)){
            if (m_value){
                delete m_value;
                m_value = 0;
            }
        }
        if (!m_value) m_value = new char[size];
        strncpy(m_value, value, valuelen);
        m_value[size - 1] = 0;
    }
}

//------------------------------------------------//
Parser::Value::Value(const char* text) : m_text(0), m_pos(0), m_value(0), m_bend(false)
{
    if (text){
        size_t size = strlen(text) + 1;
        m_text = new char[size];
        strcpy(m_text, text);
        m_text[size- 1] = 0;
    }
}

Parser::Value::~Value()
{
    if (m_text){
        delete m_text;
        m_text = 0;
    }
}

const char* Parser::Value::First()
{
    m_pos = m_text;
    return this->Next();
}

const char* Parser::Value::Next()
{   
    if (m_bend) return 0;
    const char* p = m_pos;
    if (!p || !p[0]) return 0;

    int ignore = 0;
    bool end = true;
    do {
        if ('(' == p[0]){ ++ignore; continue; }
        else if (')' == p[0]){ --ignore; continue; }
        if (ignore) continue;

        if (',' == p[0]){
            end = false;
            break;
        }
    } while ((++p)[0]);

    m_bend = end;

    const char* iB = m_pos;
    m_pos = p + 1;
    if ('(' == iB[0]) ++iB;

    if (m_value) delete m_value;
    m_value = new char[p - iB + 1];
    strncpy(m_value, iB, p - iB);
    m_value[p - iB] = 0;

    size_t size = strlen(m_value);
    if (')' == m_value[size - 1]){
        m_value[size - 1] = 0;
    }
    
    return m_value;
}

EDUI_NAMESPACE_END
